home *** CD-ROM | disk | FTP | other *** search
/ MacTech 1 to 12 / MacTech-vol-1-12.toast / Source / MacTech® Magazine / Volume 04 - 1988 / 04.06 Jun 88 / icon source / IconMenu.Pas next >
Encoding:
Pascal/Delphi Source File  |  1987-09-25  |  6.0 KB  |  232 lines  |  [TEXT/EDIT]

  1. {
  2. |    Icon menu MDEF unit
  3. |
  4. |    Creates and manages a menu of Icons. 
  5. }
  6. unit IconMenu;
  7.  
  8. interface
  9.  
  10. uses
  11.     Macintf, StdPoll, StdMenu;
  12.     
  13. type
  14.     IconMenuHdlr = object (MenuHdlr)
  15.         StartIcon,    { The resource ID of first icon }
  16.         NumIcons,    { How many icons to use (ID's in sequence) }
  17.         IconsWide,    { Menu shape... }
  18.         IconsTall,    { More menu shape. }
  19.         BufferSpace    { Extra white pixels around each icon }
  20.             : Integer;
  21.         Title         { The name of the menu }
  22.             : Str255;
  23.         
  24.         procedure Create (RsrcID : Integer); override;
  25.         procedure Setup (
  26.             StartIconReq, 
  27.             NumIconsReq,
  28.             IconsWideReq,
  29.             BufferSpaceReq 
  30.                 : Integer;
  31.             TitleReq
  32.                 : Str255);  end;
  33.     
  34.     IconMenuPtr = ^IconMenuInfo;
  35.     IconMenuHandle = ^ IconMenuPtr;
  36.     
  37.     IconMenuInfo = record
  38.         StdStuff : MenuInfo; { The default MenuInfo record }
  39.         Handler : IconMenuHdlr { Reference to the above handler object }
  40.             end; 
  41.  
  42. {------------------------------------------------------------------------}
  43. implementation
  44.  
  45. const
  46.       IconSize = 32;    { How big is an icon }
  47.  
  48. {
  49. |    IconMenuDef is installed as the MDEF procedure. 
  50. |    See IM Vol. I, p. 362
  51. }
  52. procedure IconMenuDef (
  53.     Message : Integer;
  54.     SelectedMenu : IconMenuHandle;
  55.     var MenuRect : Rect;
  56.     HitPt : Point;
  57.     var WhichItem : Integer);
  58.  
  59.     {
  60.     |    ItemRect - function to find the rectangle ( in global 
  61.     |    coordinates) of a given item number.
  62.     }
  63.     function ItemRect (
  64.         ItemNum : Integer;
  65.         MenuRect : Rect; 
  66.          SelectedMenu : IconMenuHandle) : Rect;
  67.       
  68.     var
  69.         TempRect 
  70.             : Rect;
  71.         ItemLess1,
  72.         ItemSize 
  73.             : Integer;
  74.       
  75.     begin
  76.           { If ItemNum is a real item, then return the }
  77.         { global coordinates of the item's rectangle; }
  78.         { otherwise return empty rect. }
  79.         if (ItemNum >= 1) 
  80.         and (ItemNum <= SelectedMenu^^.Handler.NumIcons)
  81.         then with SelectedMenu^^.Handler do begin 
  82.             ItemLess1 := ItemNum - 1;
  83.             ItemSize := IconSize + 2 * BufferSpace;
  84.             TempRect.top := (ItemLess1 div IconsWide) 
  85.                     * ItemSize + MenuRect.top;
  86.             TempRect.left := (ItemLess1 mod IconsWide) 
  87.                     * ItemSize + MenuRect.left;
  88.             TempRect.bottom := TempRect.top + ItemSize;
  89.             TempRect.right := TempRect.left + ItemSize end
  90.         else begin
  91.               TempRect.top := 0;
  92.               TempRect.left := 0;
  93.               TempRect.bottom := 0;
  94.               TempRect.right := 0 end;
  95.           ItemRect := TempRect end; 
  96.  
  97.     {
  98.     |    DoDrawMessage - handle the menu manager Draw command
  99.     }
  100.     procedure DoDrawMessage (
  101.         SelectedMenu : IconMenuHandle;
  102.           MenuRect : Rect);
  103.        
  104.     var
  105.               Selection : Integer; { Current selection }
  106.               SelRect : Rect;    { Current selection's Rectangle }
  107.               TheIcon : Handle; { Handle to the selection's Icon }
  108.         
  109.     begin
  110.         { Get every icon in the menu and plot it. }
  111.         Hlock(Handle(SelectedMenu));
  112.         with SelectedMenu^^.Handler do begin
  113.                   for Selection := 1 to NumIcons do begin
  114.                   SelRect := ItemRect(Selection, MenuRect, SelectedMenu);
  115.                   InsetRect(SelRect,BufferSpace,BufferSpace);
  116.                   TheIcon := GetIcon (StartIcon + Selection - 1);
  117.                   PlotIcon (SelRect, TheIcon) end end;
  118.         HUnlock(Handle(SelectedMenu)) end; 
  119.             
  120.     {
  121.     |    DoChooseMessage - handle the menu manager Choose command
  122.     }
  123.      function DoChooseMessage (
  124.         SelectedMenu : IconMenuHandle;
  125.           MenuRect : Rect;
  126.         HitPoint : Point;
  127.         OldSelection : Integer) : Integer;
  128.         var
  129.               SelRect : Rect;
  130.               Found : boolean;
  131.               Selection : Integer;
  132.               OldSelRect : Rect;
  133.         begin
  134.          Selection := 1;
  135.         Found:= false;
  136.         { Find out which item mouse is over, if any. }
  137.               repeat
  138.                 SelRect := ItemRect (Selection, MenuRect, SelectedMenu);
  139.             Found := PtInRect (HitPoint,SelRect); 
  140.             if not Found 
  141.             then Selection := Selection + 1;
  142.                   until ((Selection > (SelectedMenu^^.Handler.NumIcons))
  143.                 or (Found));
  144.                { Update hiliting as necessary }
  145.         if Found 
  146.         then begin { in an item }
  147.               if (Selection <> OldSelection) 
  148.             then begin { in a different item, change hiliting }
  149.                       OldSelRect := ItemRect(OldSelection, 
  150.                     MenuRect, SelectedMenu);
  151.                       InvertRect(OldSelRect);
  152.                       InvertRect(SelRect) end;
  153.               DoChooseMessage := Selection end
  154.               else begin { not in a item, unhilite old }
  155.                 OldSelRect := ItemRect(OldSelection, MenuRect, SelectedMenu);
  156.                   InvertRect (OldSelRect);
  157.             DoChooseMessage := 0 end end;
  158.  
  159.     {
  160.     |    DoSizeMessage - handle the menu manager Size command
  161.     }
  162.       procedure DoSizeMessage (
  163.         var Menu : IconMenuHandle);
  164.         begin
  165.               with Menu^^.Handler do begin
  166.                   Menu^^.StdStuff.menuWidth 
  167.                   := IconsWide*(IconSize + 2 * BufferSpace);
  168.                   Menu^^.StdStuff.menuHeight 
  169.                   := IconsTall*(IconSize + 2 * BufferSpace)
  170.                     end end;
  171.  
  172. {
  173. |    IconMenuDef - main
  174. }
  175. begin
  176.       case message of
  177.             mSizeMsg : DoSizeMessage (SelectedMenu);
  178.               mDrawMsg : DoDrawMessage (SelectedMenu, MenuRect);
  179.         mChooseMsg : WhichItem := DoChooseMessage (
  180.                 SelectedMenu,MenuRect,HitPt,WhichItem) end end;
  181.  
  182. function Min (a,b : Integer) : Integer;
  183. begin 
  184.     if a < b
  185.     then Min := a
  186.     else Min := b end;
  187.  
  188. procedure IconMenuHdlr.Setup (
  189.             StartIconReq, 
  190.             NumIconsReq,
  191.             IconsWideReq,
  192.             BufferSpaceReq 
  193.                 : Integer;
  194.             TitleReq
  195.                 : Str255);
  196. begin
  197.     StartIcon := StartIconReq;
  198.     NumIcons := NumIconsReq;
  199.     IconsWide := IconsWideReq;
  200.     { Calculate IconsTall from NumIcons and IconsWide }
  201.     IconsTall := NumIcons div IconsWide 
  202.             + Min (NumIcons mod IconsWide, 1);
  203.     BufferSpace := BufferSpaceReq;
  204.     Title := TitleReq end;
  205.  
  206. procedure IconMenuHdlr.Create (RsrcID : Integer);
  207.     { RsrcID isn't really a resource ID in this case, just a menu id }
  208. var
  209.     TrickyHandle : IconMenuHandle; { Used for type coercion }
  210.  
  211. begin 
  212.     HLock(Handle(Self));
  213.     TheMenu := NewMenu (RsrcID, Title); { Get a plain menu record }
  214.     
  215.     SetHandleSize (Handle(TheMenu), SizeOf(IconMenuInfo)); { Stretch it }
  216.     if MemError = 0
  217.     then begin
  218.         { Assign the icon MDEF proc }
  219.         TheMenu^^.menuProc := NewHandle(0); { Very Important! }
  220.         TheMenu^^.menuProc^ := @IconMenuDef;
  221.         { Stuff in reference to the MenuHandler object }
  222.         TrickyHandle := IconMenuHandle (TheMenu);
  223.         TrickyHandle^^.Handler := SELF;
  224.         { Insert at end of menu bar }
  225.         CalcMenuSize (TheMenu);
  226.         InsertMenu (TheMenu,0) end
  227.     else
  228.         SysBeep (1);
  229.     HUnlock(Handle(Self)) end;
  230.     
  231. end. { of IconMenu unit }
  232.